package site.wanjiahao.protocol;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import site.wanjiahao.message.Message;

import java.util.List;

import static site.wanjiahao.protocol.MessageCodec.MessageConstant.MAGIC;
import static site.wanjiahao.protocol.MessageCodec.MessageConstant.VERSION;
import static site.wanjiahao.util.ConfigPropertiesHolder.getSerializeAlgorithm;


/**
 * 自定义消息编解码器
 * 可以继承至
 *
 * @ByteToMessageCodec 但是这个消息编解码器不能标注可共享注解
 */
@ChannelHandler.Sharable
public class MessageCodec extends MessageToMessageCodec<ByteBuf, Message> {

    @Override
    protected void encode(ChannelHandlerContext ctx, Message msg, List<Object> out) {
        ByteBuf buffer = ctx.alloc().buffer();
        // 消息的魔数类型
        buffer.writeBytes(MAGIC);
        // 消息版本号
        buffer.writeInt(VERSION);
        // 消息的序列化算法
        buffer.writeByte(getSerializeAlgorithm().ordinal());
        // 消息的请求类型
        buffer.writeInt(msg.getMessageType());
        // 消息的请求序列号
        buffer.writeLong(msg.getSequenceId());
        // 序列化对象
        byte[] bytes = getSerializeAlgorithm().serialize(msg);
        buffer.writeInt(bytes.length);
        buffer.writeBytes(bytes);
        out.add(buffer);
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) {
        // TODO check magic
        byte[] magic = new byte[4];
         msg.readBytes(magic, 0, 4);
        // TODO check version
        int version = msg.readInt();
        // TODO check serialize
        int serialize = msg.readByte();
        // 读取消息类型, 对应的id
        int messageType = msg.readInt();
        long sequenceId = msg.readLong();
        // 读取4个字节的长度
        int length = msg.readInt();
        // 读取正文内容
        byte[] content = new byte[length];
        msg.readBytes(content, 0, length);
        // 重新设置序列化id
        Message deserialize = getSerializeAlgorithm().deserialize(content, Message.getClazz(messageType));
        deserialize.setSequenceId(sequenceId);
        out.add(deserialize);
    }

    /**
     * 内部数据，保证外部不被访问
     */
    static class MessageConstant {

        /**
         * 魔数类型
         */
        static final byte[] MAGIC = {'C', 'A', 'F', 'E'};

        /**
         * 版本号
         */
        static final int VERSION = 1;

    }
}
